/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */#include"LayerManagerComposite.h"#include<stddef.h> // for size_t#include<stdint.h> // for uint16_t, uint32_t#include"CanvasLayerComposite.h" // for CanvasLayerComposite#include"ColorLayerComposite.h" // for ColorLayerComposite#include"CompositableHost.h" // for CompositableHost#include"ContainerLayerComposite.h" // for ContainerLayerComposite, etc#include"Diagnostics.h"#include"FPSCounter.h" // for FPSState, FPSCounter#include"FrameMetrics.h" // for FrameMetrics#include"GeckoProfiler.h" // for profiler_*#include"ImageLayerComposite.h" // for ImageLayerComposite#include"Layers.h" // for Layer, ContainerLayer, etc#include"LayerScope.h" // for LayerScope Tool#include"protobuf/LayerScopePacket.pb.h" // for protobuf (LayerScope)#include"PaintedLayerComposite.h" // for PaintedLayerComposite#include"TiledContentHost.h"#include"Units.h" // for ScreenIntRect#include"UnitTransforms.h" // for ViewAs#include"apz/src/AsyncPanZoomController.h" // for AsyncPanZoomController#include"gfxPrefs.h" // for gfxPrefs#ifdef XP_MACOSX#include"gfxPlatformMac.h"#endif#include"gfxRect.h" // for gfxRect#include"gfxUtils.h" // for frame color util#include"mozilla/Assertions.h" // for MOZ_ASSERT, etc#include"mozilla/RefPtr.h" // for RefPtr, already_AddRefed#include"mozilla/gfx/2D.h" // for DrawTarget#include"mozilla/gfx/Matrix.h" // for Matrix4x4#include"mozilla/gfx/Point.h" // for IntSize, Point#include"mozilla/gfx/Rect.h" // for Rect#include"mozilla/gfx/Types.h" // for Color, SurfaceFormat#include"mozilla/layers/Compositor.h" // for Compositor#include"mozilla/layers/CompositorTypes.h"#include"mozilla/layers/Effects.h" // for Effect, EffectChain, etc#include"mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper#include"mozilla/layers/LayersTypes.h" // for etc#include"mozilla/widget/CompositorWidget.h" // for WidgetRenderingContext#include"ipc/CompositorBench.h" // for CompositorBench#include"ipc/ShadowLayerUtils.h"#include"mozilla/mozalloc.h" // for operator new, etc#include"nsAppRunner.h"#include"mozilla/RefPtr.h" // for nsRefPtr#include"nsCOMPtr.h" // for already_AddRefed#include"nsDebug.h" // for NS_WARNING, NS_RUNTIMEABORT, etc#include"nsISupportsImpl.h" // for Layer::AddRef, etc#include"nsPoint.h" // for nsIntPoint#include"nsRect.h" // for mozilla::gfx::IntRect#include"nsRegion.h" // for nsIntRegion, etc#if defined(MOZ_WIDGET_ANDROID)#include<android/log.h>#include<android/native_window.h>#include"mozilla/widget/AndroidCompositorWidget.h"#include"opengl/CompositorOGL.h"#include"GLConsts.h"#include"GLContextEGL.h"#include"GLContextProvider.h"#include"mozilla/Unused.h"#include"mozilla/widget/AndroidCompositorWidget.h"#include"ScopedGLHelpers.h"#endif#include"GeckoProfiler.h"#include"TextRenderer.h" // for TextRenderer#include"mozilla/layers/CompositorBridgeParent.h"#include"TreeTraversal.h" // for ForEachNode#ifdef USE_SKIA#include"PaintCounter.h" // For PaintCounter#endifclassgfxContext;namespacemozilla{namespacelayers{classImageLayer;usingnamespacemozilla::gfx;usingnamespacemozilla::gl;staticLayerComposite*ToLayerComposite(Layer*aLayer){returnstatic_cast<LayerComposite*>(aLayer->ImplData());}staticvoidClearSubtree(Layer*aLayer){ForEachNode<ForwardIterator>(aLayer,[](Layer*layer){ToLayerComposite(layer)->CleanupResources();});}voidLayerManagerComposite::ClearCachedResources(Layer*aSubtree){MOZ_ASSERT(!aSubtree||aSubtree->Manager()==this);Layer*subtree=aSubtree?aSubtree:mRoot.get();if(!subtree){return;}ClearSubtree(subtree);// FIXME [bjacob]// XXX the old LayerManagerOGL code had a mMaybeInvalidTree that it set to true here.// Do we need that?}HostLayerManager::HostLayerManager():mDebugOverlayWantsNextFrame(false),mWarningLevel(0.0f),mCompositorBridgeID(0),mWindowOverlayChanged(false),mLastPaintTime(TimeDuration::Forever()),mRenderStartTime(TimeStamp::Now()){}HostLayerManager::~HostLayerManager(){}voidHostLayerManager::RecordPaintTimes(constPaintTiming&aTiming){mDiagnostics->RecordPaintTimes(aTiming);}voidHostLayerManager::RecordUpdateTime(floataValue){mDiagnostics->RecordUpdateTime(aValue);}/** * LayerManagerComposite */LayerManagerComposite::LayerManagerComposite(Compositor*aCompositor):mUnusedApzTransformWarning(false),mDisabledApzWarning(false),mCompositor(aCompositor),mInTransaction(false),mIsCompositorReady(false)#if defined(MOZ_WIDGET_ANDROID),mScreenPixelsTarget(nullptr)#endif // defined(MOZ_WIDGET_ANDROID){mTextRenderer=newTextRenderer();mDiagnostics=MakeUnique<Diagnostics>();MOZ_ASSERT(aCompositor);#ifdef USE_SKIAmPaintCounter=nullptr;#endif}LayerManagerComposite::~LayerManagerComposite(){Destroy();}voidLayerManagerComposite::Destroy(){if(!mDestroyed){mCompositor->GetWidget()->CleanupWindowEffects();if(mRoot){RootLayer()->Destroy();}mCompositor->CancelFrame();mRoot=nullptr;mClonedLayerTreeProperties=nullptr;mDestroyed=true;#ifdef USE_SKIAmPaintCounter=nullptr;#endif}}voidLayerManagerComposite::UpdateRenderBounds(constIntRect&aRect){mRenderBounds=aRect;}boolLayerManagerComposite::AreComponentAlphaLayersEnabled(){returnmCompositor->GetBackendType()!=LayersBackend::LAYERS_BASIC&&mCompositor->SupportsEffect(EffectTypes::COMPONENT_ALPHA)&&LayerManager::AreComponentAlphaLayersEnabled();}boolLayerManagerComposite::BeginTransaction(){mInTransaction=true;if(!mCompositor->Ready()){returnfalse;}mIsCompositorReady=true;returntrue;}voidLayerManagerComposite::BeginTransactionWithDrawTarget(DrawTarget*aTarget,constIntRect&aRect){mInTransaction=true;if(!mCompositor->Ready()){return;}#ifdef MOZ_LAYERS_HAVE_LOGMOZ_LAYERS_LOG(("[----- BeginTransaction"));Log();#endifif(mDestroyed){NS_WARNING("Call on destroyed layer manager");return;}mIsCompositorReady=true;mCompositor->SetTargetContext(aTarget,aRect);mTarget=aTarget;mTargetBounds=aRect;}voidLayerManagerComposite::PostProcessLayers(nsIntRegion&aOpaqueRegion){LayerIntRegionvisible;LayerComposite*rootComposite=static_cast<LayerComposite*>(mRoot->AsHostLayer());PostProcessLayers(mRoot,aOpaqueRegion,visible,ViewAs<RenderTargetPixel>(rootComposite->GetShadowClipRect(),PixelCastJustification::RenderTargetIsParentLayerForRoot),Nothing());}// We want to skip directly through ContainerLayers that don't have an intermediate// surface. We compute occlusions for leaves and intermediate surfaces against// the layer that they actually composite into so that we can use the final (snapped)// effective transform.boolShouldProcessLayer(Layer*aLayer){if(!aLayer->AsContainerLayer()){returntrue;}returnaLayer->AsContainerLayer()->UseIntermediateSurface();}/** * Get accumulated transform of from the context creating layer to the * given layer. */staticMatrix4x4GetAccTransformIn3DContext(Layer*aLayer){Matrix4x4transform=aLayer->GetLocalTransform();for(Layer*layer=aLayer->GetParent();layer&&layer->Extend3DContext();layer=layer->GetParent()){transform=transform*layer->GetLocalTransform();}returntransform;}voidLayerManagerComposite::PostProcessLayers(Layer*aLayer,nsIntRegion&aOpaqueRegion,LayerIntRegion&aVisibleRegion,constMaybe<RenderTargetIntRect>&aRenderTargetClip,constMaybe<ParentLayerIntRect>&aClipFromAncestors){// Compute a clip that's the combination of our layer clip with the clip// from our ancestors.LayerComposite*composite=static_cast<LayerComposite*>(aLayer->AsHostLayer());Maybe<ParentLayerIntRect>layerClip=composite->GetShadowClipRect();MOZ_ASSERT(!layerClip||!aLayer->Combines3DTransformWithAncestors(),"The layer with a clip should not participate ""a 3D rendering context");Maybe<ParentLayerIntRect>outsideClip=IntersectMaybeRects(layerClip,aClipFromAncestors);Maybe<LayerIntRect>insideClip;if(aLayer->Extend3DContext()){// If we're preserve-3d just pass the clip rect down directly, and we'll do the// conversion at the preserve-3d leaf Layer.if(outsideClip){insideClip=Some(ViewAs<LayerPixel>(*outsideClip,PixelCastJustification::MovingDownToChildren));}}elseif(outsideClip){// Convert the combined clip into our pre-transform coordinate space, so// that it can later be intersected with our visible region.// If our transform is a perspective, there's no meaningful insideClip rect// we can compute (it would need to be a cone).Matrix4x4localTransform=GetAccTransformIn3DContext(aLayer);if(!localTransform.HasPerspectiveComponent()&&localTransform.Invert()){LayerRectinsideClipFloat=UntransformBy(ViewAs<ParentLayerToLayerMatrix4x4>(localTransform),ParentLayerRect(*outsideClip),LayerRect::MaxIntRect()).valueOr(LayerRect());insideClipFloat.RoundOut();LayerIntRectinsideClipInt;if(insideClipFloat.ToIntRect(&insideClipInt)){insideClip=Some(insideClipInt);}}}Maybe<ParentLayerIntRect>ancestorClipForChildren;if(insideClip){ancestorClipForChildren=Some(ViewAs<ParentLayerPixel>(*insideClip,PixelCastJustification::MovingDownToChildren));}if(!ShouldProcessLayer(aLayer)){MOZ_ASSERT(aLayer->AsContainerLayer()&&!aLayer->AsContainerLayer()->UseIntermediateSurface());// For layers participating 3D rendering context, their visible// region should be empty (invisible), so we pass through them// without doing anything.for(Layer*child=aLayer->GetLastChild();child;child=child->GetPrevSibling()){LayerComposite*childComposite=static_cast<LayerComposite*>(child->AsHostLayer());Maybe<RenderTargetIntRect>renderTargetClip=aRenderTargetClip;if(childComposite->GetShadowClipRect()){RenderTargetIntRectclip=TransformBy(ViewAs<ParentLayerToRenderTargetMatrix4x4>(aLayer->GetEffectiveTransform(),PixelCastJustification::RenderTargetIsParentLayerForRoot),*childComposite->GetShadowClipRect());renderTargetClip=IntersectMaybeRects(renderTargetClip,Some(clip));}PostProcessLayers(child,aOpaqueRegion,aVisibleRegion,renderTargetClip,ancestorClipForChildren);}return;}nsIntRegionlocalOpaque;// Treat layers on the path to the root of the 3D rendering context as// a giant layer if it is a leaf.Matrix4x4transform=aLayer->GetEffectiveTransform();Matrixtransform2d;Maybe<IntPoint>integerTranslation;// If aLayer has a simple transform (only an integer translation) then we// can easily convert aOpaqueRegion into pre-transform coordinates and include// that region.if(transform.Is2D(&transform2d)){if(transform2d.IsIntegerTranslation()){integerTranslation=Some(IntPoint::Truncate(transform2d.GetTranslation()));localOpaque=aOpaqueRegion;localOpaque.MoveBy(-*integerTranslation);}}// Save the value of localOpaque, which currently stores the region obscured// by siblings (and uncles and such), before our descendants contribute to it.nsIntRegionobscured=localOpaque;// Recurse on our descendants, in front-to-back order. In this process:// - Occlusions are computed for them, and they contribute to localOpaque.// - They recalculate their visible regions, taking ancestorClipForChildren// into account, and accumulate them into descendantsVisibleRegion.LayerIntRegiondescendantsVisibleRegion;boolhasPreserve3DChild=false;for(Layer*child=aLayer->GetLastChild();child;child=child->GetPrevSibling()){MOZ_ASSERT(aLayer->AsContainerLayer()->UseIntermediateSurface());LayerComposite*childComposite=static_cast<LayerComposite*>(child->AsHostLayer());PostProcessLayers(child,localOpaque,descendantsVisibleRegion,ViewAs<RenderTargetPixel>(childComposite->GetShadowClipRect(),PixelCastJustification::RenderTargetIsParentLayerForRoot),ancestorClipForChildren);if(child->Extend3DContext()){hasPreserve3DChild=true;}}// Recalculate our visible region.LayerIntRegionvisible=composite->GetShadowVisibleRegion();// If we have descendants, throw away the visible region stored on this// layer, and use the region accumulated by our descendants instead.if(aLayer->GetFirstChild()&&!hasPreserve3DChild){visible=descendantsVisibleRegion;}// Subtract any areas that we know to be opaque.if(!obscured.IsEmpty()){visible.SubOut(LayerIntRegion::FromUnknownRegion(obscured));}// Clip the visible region using the combined clip.if(insideClip){visible.AndWith(*insideClip);}composite->SetShadowVisibleRegion(visible);// Transform the newly calculated visible region into our parent's space,// apply our clip to it (if any), and accumulate it into |aVisibleRegion|// for the caller to use.ParentLayerIntRegionvisibleParentSpace=TransformBy(ViewAs<LayerToParentLayerMatrix4x4>(transform),visible);aVisibleRegion.OrWith(ViewAs<LayerPixel>(visibleParentSpace,PixelCastJustification::MovingDownToChildren));// If we have a simple transform, then we can add our opaque area into// aOpaqueRegion.if(integerTranslation&&!aLayer->HasMaskLayers()&&aLayer->IsOpaqueForVisibility()){if(aLayer->IsOpaque()){localOpaque.OrWith(composite->GetFullyRenderedRegion());}localOpaque.MoveBy(*integerTranslation);if(aRenderTargetClip){localOpaque.AndWith(aRenderTargetClip->ToUnknownRect());}aOpaqueRegion.OrWith(localOpaque);}}voidLayerManagerComposite::EndTransaction(constTimeStamp&aTimeStamp,EndTransactionFlagsaFlags){NS_ASSERTION(mInTransaction,"Didn't call BeginTransaction?");NS_ASSERTION(!(aFlags&END_NO_COMPOSITE),"Shouldn't get END_NO_COMPOSITE here");mInTransaction=false;mRenderStartTime=TimeStamp::Now();if(!mIsCompositorReady){return;}mIsCompositorReady=false;#ifdef MOZ_LAYERS_HAVE_LOGMOZ_LAYERS_LOG((" ----- (beginning paint)"));Log();#endifif(mDestroyed){NS_WARNING("Call on destroyed layer manager");return;}// Set composition timestamp here because we need it in// ComputeEffectiveTransforms (so the correct video frame size is picked) and// also to compute invalid regions properly.SetCompositionTime(aTimeStamp);if(mRoot&&!(aFlags&END_NO_IMMEDIATE_REDRAW)){MOZ_ASSERT(!aTimeStamp.IsNull());UpdateAndRender();mCompositor->FlushPendingNotifyNotUsed();}mCompositor->ClearTargetContext();mTarget=nullptr;#ifdef MOZ_LAYERS_HAVE_LOGLog();MOZ_LAYERS_LOG(("]----- EndTransaction"));#endif}voidLayerManagerComposite::UpdateAndRender(){nsIntRegioninvalid;// The results of our drawing always go directly into a pixel buffer,// so we don't need to pass any global transform here.mRoot->ComputeEffectiveTransforms(gfx::Matrix4x4());nsIntRegionopaque;PostProcessLayers(opaque);if(mClonedLayerTreeProperties){// We need to compute layer tree differences even if we're not going to// immediately use the resulting damage area, since ComputeDifferences// is also responsible for invalidates intermediate surfaces in// ContainerLayers.nsIntRegionchanged=mClonedLayerTreeProperties->ComputeDifferences(mRoot,nullptr);if(mTarget){// Since we're composing to an external target, we're not going to use// the damage region from layers changes - we want to composite// everything in the target bounds. Instead we accumulate the layers// damage region for the next window composite.mInvalidRegion.Or(mInvalidRegion,changed);}else{invalid=Move(changed);}}if(mTarget){invalid.Or(invalid,mTargetBounds);}else{// If we didn't have a previous layer tree, invalidate the entire render// area.if(!mClonedLayerTreeProperties){invalid.Or(invalid,mRenderBounds);}// Add any additional invalid rects from the window manager or previous// damage computed during ComposeToTarget().invalid.Or(invalid,mInvalidRegion);mInvalidRegion.SetEmpty();}if(invalid.IsEmpty()&&!mWindowOverlayChanged){// Composition requested, but nothing has changed. Don't do any work.mClonedLayerTreeProperties=LayerProperties::CloneFrom(GetRoot());return;}// We don't want our debug overlay to cause more frames to happen// so we will invalidate after we've decided if something changed.InvalidateDebugOverlay(invalid,mRenderBounds);Render(invalid,opaque);#if defined(MOZ_WIDGET_ANDROID)RenderToPresentationSurface();#endifmWindowOverlayChanged=false;// Update cached layer tree information.mClonedLayerTreeProperties=LayerProperties::CloneFrom(GetRoot());}already_AddRefed<DrawTarget>LayerManagerComposite::CreateOptimalMaskDrawTarget(constIntSize&aSize){MOZ_CRASH("Should only be called on the drawing side");returnnullptr;}LayerComposite*LayerManagerComposite::RootLayer()const{if(mDestroyed){NS_WARNING("Call on destroyed layer manager");returnnullptr;}returnToLayerComposite(mRoot);}voidLayerManagerComposite::InvalidateDebugOverlay(nsIntRegion&aInvalidRegion,constIntRect&aBounds){booldrawFps=gfxPrefs::LayersDrawFPS();booldrawFrameColorBars=gfxPrefs::CompositorDrawColorBars();if(drawFps){aInvalidRegion.Or(aInvalidRegion,nsIntRect(0,0,650,400));}if(drawFrameColorBars){aInvalidRegion.Or(aInvalidRegion,nsIntRect(0,0,10,aBounds.height));}#ifdef USE_SKIAbooldrawPaintTimes=gfxPrefs::AlwaysPaint();if(drawPaintTimes){aInvalidRegion.Or(aInvalidRegion,nsIntRect(PaintCounter::GetPaintRect()));}#endif}#ifdef USE_SKIAvoidLayerManagerComposite::DrawPaintTimes(Compositor*aCompositor){if(!mPaintCounter){mPaintCounter=newPaintCounter();}TimeDurationcompositeTime=TimeStamp::Now()-mRenderStartTime;mPaintCounter->Draw(aCompositor,mLastPaintTime,compositeTime);}#endifstaticuint16_tsFrameCount=0;voidLayerManagerComposite::RenderDebugOverlay(constIntRect&aBounds){booldrawFps=gfxPrefs::LayersDrawFPS();booldrawFrameColorBars=gfxPrefs::CompositorDrawColorBars();if(drawFps){floatalpha=1;#ifdef ANDROID// Draw a translation delay warning overlayintwidth;intborder;TimeStampnow=TimeStamp::Now();if(!mWarnTime.IsNull()&&(now-mWarnTime).ToMilliseconds()<kVisualWarningDuration){EffectChaineffects;// Black blorderborder=4;width=6;effects.mPrimaryEffect=newEffectSolidColor(gfx::Color(0,0,0,1));mCompositor->DrawQuad(gfx::Rect(border,border,aBounds.width-2*border,width),aBounds,effects,alpha,gfx::Matrix4x4());mCompositor->DrawQuad(gfx::Rect(border,aBounds.height-border-width,aBounds.width-2*border,width),aBounds,effects,alpha,gfx::Matrix4x4());mCompositor->DrawQuad(gfx::Rect(border,border+width,width,aBounds.height-2*border-width*2),aBounds,effects,alpha,gfx::Matrix4x4());mCompositor->DrawQuad(gfx::Rect(aBounds.width-border-width,border+width,width,aBounds.height-2*border-2*width),aBounds,effects,alpha,gfx::Matrix4x4());// Contentborder=5;width=4;effects.mPrimaryEffect=newEffectSolidColor(gfx::Color(1,1.f-mWarningLevel,0,1));mCompositor->DrawQuad(gfx::Rect(border,border,aBounds.width-2*border,width),aBounds,effects,alpha,gfx::Matrix4x4());mCompositor->DrawQuad(gfx::Rect(border,aBounds.height-border-width,aBounds.width-2*border,width),aBounds,effects,alpha,gfx::Matrix4x4());mCompositor->DrawQuad(gfx::Rect(border,border+width,width,aBounds.height-2*border-width*2),aBounds,effects,alpha,gfx::Matrix4x4());mCompositor->DrawQuad(gfx::Rect(aBounds.width-border-width,border+width,width,aBounds.height-2*border-2*width),aBounds,effects,alpha,gfx::Matrix4x4());SetDebugOverlayWantsNextFrame(true);}#endifGPUStatsstats;stats.mScreenPixels=mRenderBounds.width*mRenderBounds.height;mCompositor->GetFrameStats(&stats);std::stringtext=mDiagnostics->GetFrameOverlayString(stats);mTextRenderer->RenderText(mCompositor,text,IntPoint(2,5),Matrix4x4(),24,600,TextRenderer::FontType::FixedWidth);if(mUnusedApzTransformWarning){// If we have an unused APZ transform on this composite, draw a 20x20 red box// in the top-right cornerEffectChaineffects;effects.mPrimaryEffect=newEffectSolidColor(gfx::Color(1,0,0,1));mCompositor->DrawQuad(gfx::Rect(aBounds.width-20,0,20,20),aBounds,effects,alpha,gfx::Matrix4x4());mUnusedApzTransformWarning=false;SetDebugOverlayWantsNextFrame(true);}if(mDisabledApzWarning){// If we have a disabled APZ on this composite, draw a 20x20 yellow box// in the top-right corner, to the left of the unused-apz-transform// warning boxEffectChaineffects;effects.mPrimaryEffect=newEffectSolidColor(gfx::Color(1,1,0,1));mCompositor->DrawQuad(gfx::Rect(aBounds.width-40,0,20,20),aBounds,effects,alpha,gfx::Matrix4x4());mDisabledApzWarning=false;SetDebugOverlayWantsNextFrame(true);}}if(drawFrameColorBars){gfx::IntRectsideRect(0,0,10,aBounds.height);EffectChaineffects;effects.mPrimaryEffect=newEffectSolidColor(gfxUtils::GetColorForFrameNumber(sFrameCount));mCompositor->DrawQuad(Rect(sideRect),sideRect,effects,1.0,gfx::Matrix4x4());}if(drawFrameColorBars){// We intentionally overflow at 2^16.sFrameCount++;}#ifdef USE_SKIAbooldrawPaintTimes=gfxPrefs::AlwaysPaint();if(drawPaintTimes){DrawPaintTimes(mCompositor);}#endif}RefPtr<CompositingRenderTarget>LayerManagerComposite::PushGroupForLayerEffects(){// This is currently true, so just making sure that any new use of this// method is flagged for investigationMOZ_ASSERT(gfxPrefs::LayersEffectInvert()||gfxPrefs::LayersEffectGrayscale()||gfxPrefs::LayersEffectContrast()!=0.0);RefPtr<CompositingRenderTarget>previousTarget=mCompositor->GetCurrentRenderTarget();// make our render target the same size as the destination target// so that we don't have to change size if the drawing area changes.IntRectrect(previousTarget->GetOrigin(),previousTarget->GetSize());// XXX: I'm not sure if this is true or not...MOZ_ASSERT(rect.x==0&&rect.y==0);if(!mTwoPassTmpTarget||mTwoPassTmpTarget->GetSize()!=previousTarget->GetSize()||mTwoPassTmpTarget->GetOrigin()!=previousTarget->GetOrigin()){mTwoPassTmpTarget=mCompositor->CreateRenderTarget(rect,INIT_MODE_NONE);}MOZ_ASSERT(mTwoPassTmpTarget);mCompositor->SetRenderTarget(mTwoPassTmpTarget);returnpreviousTarget;}voidLayerManagerComposite::PopGroupForLayerEffects(RefPtr<CompositingRenderTarget>aPreviousTarget,IntRectaClipRect,boolaGrayscaleEffect,boolaInvertEffect,floataContrastEffect){MOZ_ASSERT(mTwoPassTmpTarget);// This is currently true, so just making sure that any new use of this// method is flagged for investigationMOZ_ASSERT(aInvertEffect||aGrayscaleEffect||aContrastEffect!=0.0);mCompositor->SetRenderTarget(aPreviousTarget);EffectChaineffectChain(RootLayer());Matrix5x4effectMatrix;if(aGrayscaleEffect){// R' = G' = B' = luminance// R' = 0.2126*R + 0.7152*G + 0.0722*B// G' = 0.2126*R + 0.7152*G + 0.0722*B// B' = 0.2126*R + 0.7152*G + 0.0722*BMatrix5x4grayscaleMatrix(0.2126f,0.2126f,0.2126f,0,0.7152f,0.7152f,0.7152f,0,0.0722f,0.0722f,0.0722f,0,0,0,0,1,0,0,0,0);effectMatrix=grayscaleMatrix;}if(aInvertEffect){// R' = 1 - R// G' = 1 - G// B' = 1 - BMatrix5x4colorInvertMatrix(-1,0,0,0,0,-1,0,0,0,0,-1,0,0,0,0,1,1,1,1,0);effectMatrix=effectMatrix*colorInvertMatrix;}if(aContrastEffect!=0.0){// Multiplying with:// R' = (1 + c) * (R - 0.5) + 0.5// G' = (1 + c) * (G - 0.5) + 0.5// B' = (1 + c) * (B - 0.5) + 0.5floatcP1=aContrastEffect+1;floathc=0.5*aContrastEffect;Matrix5x4contrastMatrix(cP1,0,0,0,0,cP1,0,0,0,0,cP1,0,0,0,0,1,-hc,-hc,-hc,0);effectMatrix=effectMatrix*contrastMatrix;}effectChain.mPrimaryEffect=newEffectRenderTarget(mTwoPassTmpTarget);effectChain.mSecondaryEffects[EffectTypes::COLOR_MATRIX]=newEffectColorMatrix(effectMatrix);mCompositor->DrawQuad(Rect(Point(0,0),Size(mTwoPassTmpTarget->GetSize())),aClipRect,effectChain,1.,Matrix4x4());}// Used to clear the 'mLayerComposited' flag at the beginning of each Render().staticvoidClearLayerFlags(Layer*aLayer){ForEachNode<ForwardIterator>(aLayer,[](Layer*layer){if(layer->AsHostLayer()){static_cast<LayerComposite*>(layer->AsHostLayer())->SetLayerComposited(false);}});}#if defined(MOZ_WIDGET_ANDROID)classScopedCompositorRenderOffset{public:ScopedCompositorRenderOffset(CompositorOGL*aCompositor,constScreenPoint&aOffset):mCompositor(aCompositor),mOriginalOffset(mCompositor->GetScreenRenderOffset()),mOriginalProjection(mCompositor->GetProjMatrix()){ScreenPointoffset(mOriginalOffset.x+aOffset.x,mOriginalOffset.y+aOffset.y);mCompositor->SetScreenRenderOffset(offset);// Calling CompositorOGL::SetScreenRenderOffset does not affect the projection matrix// so adjust that as well.gfx::Matrix4x4mat=mOriginalProjection;mat.PreTranslate(aOffset.x,aOffset.y,0.0f);mCompositor->SetProjMatrix(mat);}~ScopedCompositorRenderOffset(){mCompositor->SetScreenRenderOffset(mOriginalOffset);mCompositor->SetProjMatrix(mOriginalProjection);}private:CompositorOGL*constmCompositor;constScreenPointmOriginalOffset;constgfx::Matrix4x4mOriginalProjection;};#endif // defined(MOZ_WIDGET_ANDROID)voidLayerManagerComposite::Render(constnsIntRegion&aInvalidRegion,constnsIntRegion&aOpaqueRegion){AUTO_PROFILER_LABEL("LayerManagerComposite::Render",GRAPHICS);if(mDestroyed||!mCompositor||mCompositor->IsDestroyed()){NS_WARNING("Call on destroyed layer manager");return;}ClearLayerFlags(mRoot);// At this time, it doesn't really matter if these preferences change// during the execution of the function; we should be safe in all// permutations. However, may as well just get the values onces and// then use them, just in case the consistency becomes important in// the future.boolinvertVal=gfxPrefs::LayersEffectInvert();boolgrayscaleVal=gfxPrefs::LayersEffectGrayscale();floatcontrastVal=gfxPrefs::LayersEffectContrast();boolhaveLayerEffects=(invertVal||grayscaleVal||contrastVal!=0.0);// Set LayerScope begin/end frameLayerScopeAutoFrameframe(PR_Now());// Dump to consoleif(gfxPrefs::LayersDump()){this->Dump(/* aSorted= */true);}elseif(profiler_feature_active(ProfilerFeature::LayersDump)){std::stringstreamss;Dump(ss);profiler_tracing("log",ss.str().c_str());}// Dump to LayerScope Viewerif(LayerScope::CheckSendable()){// Create a LayersPacket, dump Layers into it and transfer the// packet('s ownership) to LayerScope.autopacket=MakeUnique<layerscope::Packet>();layerscope::LayersPacket*layersPacket=packet->mutable_layers();this->Dump(layersPacket);LayerScope::SendLayerDump(Move(packet));}mozilla::widget::WidgetRenderingContextwidgetContext;#if defined(XP_MACOSX)widgetContext.mLayerManager=this;#elif defined(MOZ_WIDGET_ANDROID)widgetContext.mCompositor=GetCompositor();#endif{AUTO_PROFILER_LABEL("LayerManagerComposite::Render:Prerender",GRAPHICS);if(!mCompositor->GetWidget()->PreRender(&widgetContext)){return;}}ParentLayerIntRectclipRect;IntRectbounds(mRenderBounds.x,mRenderBounds.y,mRenderBounds.width,mRenderBounds.height);IntRectactualBounds;CompositorBench(mCompositor,bounds);MOZ_ASSERT(mRoot->GetOpacity()==1);#if defined(MOZ_WIDGET_ANDROID)LayerMetricsWrapperwrapper=GetRootContentLayer();if(wrapper){mCompositor->SetClearColor(wrapper.Metadata().GetBackgroundColor());}else{mCompositor->SetClearColorToDefault();}#endifif(mRoot->GetClipRect()){clipRect=*mRoot->GetClipRect();IntRectrect(clipRect.x,clipRect.y,clipRect.width,clipRect.height);mCompositor->BeginFrame(aInvalidRegion,&rect,bounds,aOpaqueRegion,nullptr,&actualBounds);}else{gfx::IntRectrect;mCompositor->BeginFrame(aInvalidRegion,nullptr,bounds,aOpaqueRegion,&rect,&actualBounds);clipRect=ParentLayerIntRect(rect.x,rect.y,rect.width,rect.height);}#if defined(MOZ_WIDGET_ANDROID)ScreenCoordoffset=GetContentShiftForToolbar();ScopedCompositorRenderOffsetscopedOffset(mCompositor->AsCompositorOGL(),ScreenPoint(0.0f,offset));#endifif(actualBounds.IsEmpty()){mCompositor->GetWidget()->PostRender(&widgetContext);return;}// Allow widget to render a custom background.mCompositor->GetWidget()->DrawWindowUnderlay(&widgetContext,LayoutDeviceIntRect::FromUnknownRect(actualBounds));RefPtr<CompositingRenderTarget>previousTarget;if(haveLayerEffects){previousTarget=PushGroupForLayerEffects();}else{mTwoPassTmpTarget=nullptr;}// Render our layers.{Diagnostics::Recordrecord(mRenderStartTime);RootLayer()->Prepare(ViewAs<RenderTargetPixel>(clipRect,PixelCastJustification::RenderTargetIsParentLayerForRoot));if(record.Recording()){mDiagnostics->RecordPrepareTime(record.Duration());}}// Execute draw commands.{Diagnostics::Recordrecord;RootLayer()->RenderLayer(clipRect.ToUnknownRect(),Nothing());if(record.Recording()){mDiagnostics->RecordCompositeTime(record.Duration());}}RootLayer()->Cleanup();if(!mRegionToClear.IsEmpty()){for(autoiter=mRegionToClear.RectIter();!iter.Done();iter.Next()){constIntRect&r=iter.Get();mCompositor->ClearRect(Rect(r.x,r.y,r.width,r.height));}}if(mTwoPassTmpTarget){MOZ_ASSERT(haveLayerEffects);PopGroupForLayerEffects(previousTarget,clipRect.ToUnknownRect(),grayscaleVal,invertVal,contrastVal);}// Allow widget to render a custom foreground.mCompositor->GetWidget()->DrawWindowOverlay(&widgetContext,LayoutDeviceIntRect::FromUnknownRect(actualBounds));mCompositor->NormalDrawingDone();#if defined(MOZ_WIDGET_ANDROID)// Depending on the content shift the toolbar may be rendered on top of// some of the content so it must be rendered after the content.RenderToolbar();HandlePixelsTarget();#endif // defined(MOZ_WIDGET_ANDROID)// DebuggingRenderDebugOverlay(actualBounds);{AUTO_PROFILER_LABEL("LayerManagerComposite::Render:EndFrame",GRAPHICS);mCompositor->EndFrame();// Call after EndFrame()mCompositor->SetDispAcquireFence(mRoot);}mCompositor->GetWidget()->PostRender(&widgetContext);RecordFrame();}#if defined(MOZ_WIDGET_ANDROID)classScopedCompositorProjMatrix{public:ScopedCompositorProjMatrix(CompositorOGL*aCompositor,constMatrix4x4&aProjMatrix):mCompositor(aCompositor),mOriginalProjMatrix(mCompositor->GetProjMatrix()){mCompositor->SetProjMatrix(aProjMatrix);}~ScopedCompositorProjMatrix(){mCompositor->SetProjMatrix(mOriginalProjMatrix);}private:CompositorOGL*constmCompositor;constMatrix4x4mOriginalProjMatrix;};classScopedCompostitorSurfaceSize{public:ScopedCompostitorSurfaceSize(CompositorOGL*aCompositor,constgfx::IntSize&aSize):mCompositor(aCompositor),mOriginalSize(mCompositor->GetDestinationSurfaceSize()){mCompositor->SetDestinationSurfaceSize(aSize);}~ScopedCompostitorSurfaceSize(){mCompositor->SetDestinationSurfaceSize(mOriginalSize);}private:CompositorOGL*constmCompositor;constgfx::IntSizemOriginalSize;};classScopedContextSurfaceOverride{public:ScopedContextSurfaceOverride(GLContextEGL*aContext,void*aSurface):mContext(aContext){MOZ_ASSERT(aSurface);mContext->SetEGLSurfaceOverride(aSurface);mContext->MakeCurrent(true);}~ScopedContextSurfaceOverride(){mContext->SetEGLSurfaceOverride(EGL_NO_SURFACE);mContext->MakeCurrent(true);}private:GLContextEGL*constmContext;};voidLayerManagerComposite::RenderToPresentationSurface(){widget::CompositorWidget*constwidget=mCompositor->GetWidget();ANativeWindow*window=widget->AsAndroid()->GetPresentationANativeWindow();if(!window){return;}EGLSurfacesurface=widget->AsAndroid()->GetPresentationEGLSurface();if(!surface){//create surface;surface=GLContextProviderEGL::CreateEGLSurface(window);if(!surface){return;}widget->AsAndroid()->SetPresentationEGLSurface(surface);}CompositorOGL*compositor=mCompositor->AsCompositorOGL();GLContext*gl=compositor->gl();GLContextEGL*egl=GLContextEGL::Cast(gl);if(!egl){return;}constIntSizewindowSize(ANativeWindow_getWidth(window),ANativeWindow_getHeight(window));if((windowSize.width<=0)||(windowSize.height<=0)){return;}ScreenRotationrotation=compositor->GetScreenRotation();constintactualWidth=windowSize.width;constintactualHeight=windowSize.height;constgfx::IntSizeoriginalSize=compositor->GetDestinationSurfaceSize();constnsIntRectoriginalRect=nsIntRect(0,0,originalSize.width,originalSize.height);intpageWidth=originalSize.width;intpageHeight=originalSize.height;if(rotation==ROTATION_90||rotation==ROTATION_270){pageWidth=originalSize.height;pageHeight=originalSize.width;}floatscale=1.0;if((pageWidth>actualWidth)||(pageHeight>actualHeight)){constfloatscaleWidth=(float)actualWidth/(float)pageWidth;constfloatscaleHeight=(float)actualHeight/(float)pageHeight;scale=scaleWidth<=scaleHeight?scaleWidth:scaleHeight;}constgfx::IntSizeactualSize(actualWidth,actualHeight);ScopedCompostitorSurfaceSizeoverrideSurfaceSize(compositor,actualSize);constScreenPointoffset((actualWidth-(int)(scale*pageWidth))/2,0);ScopedContextSurfaceOverrideoverrideSurface(egl,surface);MatrixviewMatrix=ComputeTransformForRotation(originalRect,rotation);viewMatrix.Invert();// unrotateviewMatrix.PostScale(scale,scale);viewMatrix.PostTranslate(offset.x,offset.y);Matrix4x4matrix=Matrix4x4::From2D(viewMatrix);mRoot->ComputeEffectiveTransforms(matrix);nsIntRegionopaque;PostProcessLayers(opaque);nsIntRegioninvalid;IntRectbounds=IntRect::Truncate(0,0,scale*pageWidth,actualHeight);IntRectrect,actualBounds;MOZ_ASSERT(mRoot->GetOpacity()==1);mCompositor->BeginFrame(invalid,nullptr,bounds,nsIntRegion(),&rect,&actualBounds);// The Java side of Fennec sets a scissor rect that accounts for// chrome such as the URL bar. Override that so that the entire frame buffer// is cleared.ScopedScissorRectscissorRect(egl,0,0,actualWidth,actualHeight);egl->fClearColor(0.0,0.0,0.0,0.0);egl->fClear(LOCAL_GL_COLOR_BUFFER_BIT);constIntRectclipRect=IntRect::Truncate(0,0,actualWidth,actualHeight);RootLayer()->Prepare(RenderTargetIntRect::FromUnknownRect(clipRect));RootLayer()->RenderLayer(clipRect,Nothing());mCompositor->EndFrame();}ScreenCoordLayerManagerComposite::GetContentShiftForToolbar(){ScreenCoordresult(0.0f);// If GetTargetContext return is not null we are not drawing to the screen so there will not be any content offset.if(mCompositor->GetTargetContext()!=nullptr){returnresult;}if(CompositorBridgeParent*bridge=mCompositor->GetCompositorBridgeParent()){AndroidDynamicToolbarAnimator*animator=bridge->GetAPZCTreeManager()->GetAndroidDynamicToolbarAnimator();MOZ_RELEASE_ASSERT(animator);result.value=(float)animator->GetCurrentContentOffset().value;}returnresult;}voidLayerManagerComposite::RenderToolbar(){// If GetTargetContext return is not null we are not drawing to the screen so don't draw the toolbar.if(mCompositor->GetTargetContext()!=nullptr){return;}if(CompositorBridgeParent*bridge=mCompositor->GetCompositorBridgeParent()){AndroidDynamicToolbarAnimator*animator=bridge->GetAPZCTreeManager()->GetAndroidDynamicToolbarAnimator();MOZ_RELEASE_ASSERT(animator);int32_ttoolbarHeight=animator->GetCurrentToolbarHeight();if(toolbarHeight==0){return;}EffectChaineffects;effects.mPrimaryEffect=animator->GetToolbarEffect(mCompositor->AsCompositorOGL());// If GetToolbarEffect returns null, nothing is rendered for the static snapshot of the toolbar.// If the real toolbar chrome is not covering this portion of the surface, the clear color// of the surface will be visible. On Android the clear color is the background color of the page.if(effects.mPrimaryEffect){ScopedCompositorRenderOffsettoolbarOffset(mCompositor->AsCompositorOGL(),ScreenPoint(0.0f,-animator->GetCurrentContentOffset()));mCompositor->DrawQuad(gfx::Rect(0,0,mRenderBounds.width,toolbarHeight),IntRect(0,0,mRenderBounds.width,toolbarHeight),effects,1.0,gfx::Matrix4x4());}}}// Used by robocop tests to get a snapshot of the frame buffer.voidLayerManagerComposite::HandlePixelsTarget(){if(!mScreenPixelsTarget){return;}int32_tbufferWidth=mRenderBounds.width;int32_tbufferHeight=mRenderBounds.height;ipc::Shmemmem;if(!mScreenPixelsTarget->AllocPixelBuffer(bufferWidth*bufferHeight*sizeof(uint32_t),&mem)){// Failed to alloc shmem, Just bail out.return;}CompositorOGL*compositor=mCompositor->AsCompositorOGL();GLContext*gl=compositor->gl();MOZ_ASSERT(gl);gl->fReadPixels(0,0,bufferWidth,bufferHeight,LOCAL_GL_RGBA,LOCAL_GL_UNSIGNED_BYTE,mem.get<uint8_t>());Unused<<mScreenPixelsTarget->SendScreenPixels(mem,ScreenIntSize(bufferWidth,bufferHeight));mScreenPixelsTarget=nullptr;}#endifclassTextLayerComposite:publicTextLayer,publicLayerComposite{public:explicitTextLayerComposite(LayerManagerComposite*aManager):TextLayer(aManager,nullptr),LayerComposite(aManager){MOZ_COUNT_CTOR(TextLayerComposite);mImplData=static_cast<LayerComposite*>(this);}protected:~TextLayerComposite(){MOZ_COUNT_DTOR(TextLayerComposite);Destroy();}public:// LayerComposite ImplementationvirtualLayer*GetLayer()override{returnthis;}virtualvoidSetLayerManager(HostLayerManager*aManager)override{LayerComposite::SetLayerManager(aManager);mManager=aManager;}virtualvoidDestroy()override{mDestroyed=true;}virtualvoidRenderLayer(constgfx::IntRect&aClipRect,constMaybe<gfx::Polygon>&aGeometry)override{}virtualvoidCleanupResources()override{};virtualvoidGenEffectChain(EffectChain&aEffect)override{}CompositableHost*GetCompositableHost()override{returnnullptr;}virtualHostLayer*AsHostLayer()override{returnthis;}virtualconstchar*Name()constoverride{return"TextLayerComposite";}};classBorderLayerComposite:publicBorderLayer,publicLayerComposite{public:explicitBorderLayerComposite(LayerManagerComposite*aManager):BorderLayer(aManager,nullptr),LayerComposite(aManager){MOZ_COUNT_CTOR(BorderLayerComposite);mImplData=static_cast<LayerComposite*>(this);}protected:~BorderLayerComposite(){MOZ_COUNT_DTOR(BorderLayerComposite);Destroy();}public:// LayerComposite ImplementationvirtualLayer*GetLayer()override{returnthis;}virtualvoidSetLayerManager(HostLayerManager*aManager)override{LayerComposite::SetLayerManager(aManager);mManager=aManager;}virtualvoidDestroy()override{mDestroyed=true;}virtualvoidRenderLayer(constgfx::IntRect&aClipRect,constMaybe<gfx::Polygon>&aGeometry)override{}virtualvoidCleanupResources()override{};virtualvoidGenEffectChain(EffectChain&aEffect)override{}CompositableHost*GetCompositableHost()override{returnnullptr;}virtualHostLayer*AsHostLayer()override{returnthis;}virtualconstchar*Name()constoverride{return"BorderLayerComposite";}};already_AddRefed<PaintedLayer>LayerManagerComposite::CreatePaintedLayer(){if(mDestroyed){NS_WARNING("Call on destroyed layer manager");returnnullptr;}returnRefPtr<PaintedLayer>(newPaintedLayerComposite(this)).forget();}already_AddRefed<ContainerLayer>LayerManagerComposite::CreateContainerLayer(){if(mDestroyed){NS_WARNING("Call on destroyed layer manager");returnnullptr;}returnRefPtr<ContainerLayer>(newContainerLayerComposite(this)).forget();}already_AddRefed<ImageLayer>LayerManagerComposite::CreateImageLayer(){if(mDestroyed){NS_WARNING("Call on destroyed layer manager");returnnullptr;}returnRefPtr<ImageLayer>(newImageLayerComposite(this)).forget();}already_AddRefed<ColorLayer>LayerManagerComposite::CreateColorLayer(){if(LayerManagerComposite::mDestroyed){NS_WARNING("Call on destroyed layer manager");returnnullptr;}returnRefPtr<ColorLayer>(newColorLayerComposite(this)).forget();}already_AddRefed<CanvasLayer>LayerManagerComposite::CreateCanvasLayer(){if(LayerManagerComposite::mDestroyed){NS_WARNING("Call on destroyed layer manager");returnnullptr;}returnRefPtr<CanvasLayer>(newCanvasLayerComposite(this)).forget();}already_AddRefed<RefLayer>LayerManagerComposite::CreateRefLayer(){if(LayerManagerComposite::mDestroyed){NS_WARNING("Call on destroyed layer manager");returnnullptr;}returnRefPtr<RefLayer>(newRefLayerComposite(this)).forget();}already_AddRefed<TextLayer>LayerManagerComposite::CreateTextLayer(){if(LayerManagerComposite::mDestroyed){NS_WARNING("Call on destroyed layer manager");returnnullptr;}returnRefPtr<TextLayer>(newTextLayerComposite(this)).forget();}already_AddRefed<BorderLayer>LayerManagerComposite::CreateBorderLayer(){if(LayerManagerComposite::mDestroyed){NS_WARNING("Call on destroyed layer manager");returnnullptr;}returnRefPtr<BorderLayer>(newBorderLayerComposite(this)).forget();}LayerManagerComposite::AutoAddMaskEffect::AutoAddMaskEffect(Layer*aMaskLayer,EffectChain&aEffects):mCompositable(nullptr),mFailed(false){if(!aMaskLayer){return;}mCompositable=ToLayerComposite(aMaskLayer)->GetCompositableHost();if(!mCompositable){NS_WARNING("Mask layer with no compositable host");mFailed=true;return;}if(!mCompositable->AddMaskEffect(aEffects,aMaskLayer->GetEffectiveTransform())){mCompositable=nullptr;mFailed=true;}}LayerManagerComposite::AutoAddMaskEffect::~AutoAddMaskEffect(){if(!mCompositable){return;}mCompositable->RemoveMaskEffect();}boolLayerManagerComposite::IsCompositingToScreen()const{if(!mCompositor){returntrue;}return!mCompositor->GetTargetContext();}LayerComposite::LayerComposite(LayerManagerComposite*aManager):HostLayer(aManager),mCompositeManager(aManager),mCompositor(aManager->GetCompositor()),mDestroyed(false),mLayerComposited(false){}LayerComposite::~LayerComposite(){}voidLayerComposite::Destroy(){if(!mDestroyed){mDestroyed=true;CleanupResources();}}voidLayerComposite::AddBlendModeEffect(EffectChain&aEffectChain){gfx::CompositionOpblendMode=GetLayer()->GetEffectiveMixBlendMode();if(blendMode==gfx::CompositionOp::OP_OVER){return;}aEffectChain.mSecondaryEffects[EffectTypes::BLEND_MODE]=newEffectBlendMode(blendMode);return;}boolLayerManagerComposite::CanUseCanvasLayerForSize(constIntSize&aSize){returnmCompositor->CanUseCanvasLayerForSize(gfx::IntSize(aSize.width,aSize.height));}voidLayerManagerComposite::NotifyShadowTreeTransaction(){if(gfxPrefs::LayersDrawFPS()){mDiagnostics->AddTxnFrame();}}voidLayerComposite::SetLayerManager(HostLayerManager*aManager){HostLayer::SetLayerManager(aManager);mCompositeManager=static_cast<LayerManagerComposite*>(aManager);mCompositor=mCompositeManager->GetCompositor();}boolLayerManagerComposite::AsyncPanZoomEnabled()const{if(CompositorBridgeParent*bridge=mCompositor->GetCompositorBridgeParent()){returnbridge->GetOptions().UseAPZ();}returnfalse;}boolLayerManagerComposite::AlwaysScheduleComposite()const{return!!(mCompositor->GetDiagnosticTypes()&DiagnosticTypes::FLASH_BORDERS);}nsIntRegionLayerComposite::GetFullyRenderedRegion(){if(TiledContentHost*tiled=GetCompositableHost()?GetCompositableHost()->AsTiledContentHost():nullptr){nsIntRegionshadowVisibleRegion=GetShadowVisibleRegion().ToUnknownRegion();// Discard the region which hasn't been drawn yet when doing// progressive drawing. Note that if the shadow visible region// shrunk the tiled valig region may not have discarded this yet.shadowVisibleRegion.And(shadowVisibleRegion,tiled->GetValidRegion());returnshadowVisibleRegion;}else{returnGetShadowVisibleRegion().ToUnknownRegion();}}Matrix4x4HostLayer::GetShadowTransform(){Matrix4x4transform=mShadowTransform;Layer*layer=GetLayer();transform.PostScale(layer->GetPostXScale(),layer->GetPostYScale(),1.0f);if(constContainerLayer*c=layer->AsContainerLayer()){transform.PreScale(c->GetPreXScale(),c->GetPreYScale(),1.0f);}returntransform;}boolLayerComposite::HasStaleCompositor()const{returnmCompositeManager->GetCompositor()!=mCompositor;}#ifndef MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS/*static*/boolLayerManagerComposite::SupportsDirectTexturing(){returnfalse;}/*static*/voidLayerManagerComposite::PlatformSyncBeforeReplyUpdate(){}#endif // !defined(MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS)}// namespace layers}// namespace mozilla